package com.yifeng.repo.micro.service.server.engine.configure;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.yifeng.repo.micro.service.server.engine.core.LambdaTransformer;
import com.yifeng.repo.micro.service.server.engine.log.sqllog.SqlLogInterceptor;
import com.yifeng.repo.micro.service.server.engine.log.sqllog.SqlLogRegister;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;

import javax.annotation.Resource;

/**
 * Created by daibing on 2023/6/25.
 */
@Configuration
@EnableConfigurationProperties({ServerEngineDaoProperties.class})
public class ServerEngineDaoConfiguration implements ApplicationListener<EnvironmentChangeEvent> {
    private static final String GET = "get";
    private final ServerEngineDaoProperties mybatisPlusProperties;
    private final String dsRoutingTypeKey;
    private final String dsRoutingTypePolicy;

    @Resource
    private ConfigurableEnvironment environment;

    public ServerEngineDaoConfiguration(ServerEngineDaoProperties mybatisPlusProperties) {
        this.dsRoutingTypeKey = LambdaTransformer.getEnvironmentKey(ServerEngineDaoProperties::getDsRoutingType, GET);
        this.dsRoutingTypePolicy = LambdaTransformer.getEnvironmentKey(ServerEngineDaoProperties::getDsRoutingPolicy, GET);
        this.mybatisPlusProperties = mybatisPlusProperties;
    }

    @Bean
    public ServerEngineDynamicDataSourcePropertiesCustomizer serverEngineDynamicDataSourcePropertiesCustomizer() {
        return new ServerEngineDynamicDataSourcePropertiesCustomizer();
    }

    @Bean
    @ConditionalOnMissingBean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        if (mybatisPlusProperties.isPageEnabled()) {
            PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
            paginationInnerInterceptor.setOverflow(mybatisPlusProperties.isOverflow());
            paginationInnerInterceptor.setMaxLimit(mybatisPlusProperties.getMaxLimit());
            paginationInnerInterceptor.setDbType(mybatisPlusProperties.getDbType());
            paginationInnerInterceptor.setOptimizeJoin(mybatisPlusProperties.isOptimizeJoin());
            mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
        }
        if (mybatisPlusProperties.isSqlLogEnabled()) {
            mybatisPlusInterceptor.addInnerInterceptor(new SqlLogInterceptor());
        }
        if (mybatisPlusProperties.isOptimisticLockerEnable()) {
            mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        }
        return mybatisPlusInterceptor;
    }

    @Bean
    @ConditionalOnProperty(prefix = "yfcloud.micro.service.engine.dao", name = "sql-log-enabled", havingValue = "true")
    public SqlLogRegister sqlLogRegister(Environment environment) {
        return new SqlLogRegister(mybatisPlusProperties.getApplicationMappingPrefix(), environment);
    }

    @Override
    public void onApplicationEvent(EnvironmentChangeEvent event) {
        if (event.getKeys().isEmpty()) {
            return;
        }
        if (event.getKeys().stream().anyMatch(s -> s.startsWith(dsRoutingTypeKey))) {
            mybatisPlusProperties.setDsRoutingType(Binder.get(environment).bind(dsRoutingTypeKey, Integer.class).get());
        }
        if (event.getKeys().stream().anyMatch(s -> s.startsWith(dsRoutingTypePolicy))) {
            mybatisPlusProperties.setDsRoutingPolicy(Binder.get(environment).bind(dsRoutingTypePolicy, Bindable.mapOf(String.class, Integer.class)).get());
        }
    }

}
